#include <iostream>
#include <cstdio>

#include "../inc/Case.h"
#include "../inc/Defines.h"

using namespace std;

Case::Case()
{
	type = PLAINE;
	voisins.clear();
	bord = false;
	pol.clear();
	nbPions = 0;
	ent = NULL;
	jou = NULL;
}

Case::Case( Case* &_c)
{
	type = _c->type;
	
	for ( int i = 0 ; i < (int)_c->pol.getNbPts() ; i++ )
		pol.addPoint( _c->pol.getPoint(i) );
	
	bord = _c->bord;
	voisins = _c->voisins;
	nbPions = _c->getNbPions();
	ent = _c->ent;
	jou = NULL;
}

QString Case::getType()
{
    return type;
}

Polygone Case::getPol()
{
	return pol;
}

QList<Case*> Case::getVoisins()
{
	return voisins;
}

bool Case::getBord()
{
	return bord;
}

int Case::getNbPions()
{
	return nbPions;
}

Entite* Case::getEnt()
{
	return ent;
}

Joueur* Case::getJoueur()
{
	return jou;
}

void Case::setBord(bool _b)
{
	bord = _b;
}

void Case::setType(QString _type){
    type = _type;
}

void Case::setNbPions(int _i)
{
	nbPions = _i;
}

void Case::setEnt(Entite *_e)
{
	ent = _e;
}

void Case::setJoueur(Joueur *_j)
{
	jou = _j;
}

Case Case::operator =(const Case &_c)
{
	Case rslt;
	
	rslt.type = _c.type;
	rslt.pol = _c.pol;
	rslt.voisins = _c.voisins;
	rslt.bord = _c.bord;
	rslt.nbPions = _c.nbPions;
	rslt.ent = _c.ent;
	rslt.jou = _c.jou;
	
	return rslt;
}

int Case::getNbPts()
{
	return pol.getNbPts();
}

Point* Case::getPoint(int _i)
{
	return pol.getPoint(_i);
}

void Case::addPoint(Point* _p)
{
	Point* tmp = _p;
	pol.addPoint( tmp );
}

void Case::deleteLastPoint()
{
	pol.deleteLastPoint();
}

void Case::deletePoint(Point *_p)
{
	pol.deletePoint( _p );
}

void Case::replacePoint(Point *_p1, Point *_p2)
{
	pol.replacePoint(_p1, _p2);
}

void Case::addNeighbour(Case *_c)
{
	voisins.push_back( _c );
}

void Case::initNeighbourhood( vector<Case*> _cases)
{
	/* On parcours toutes les cases du vecteur passé en parametre et on regarde si on y trouve un point de la case appelante */
	for ( int i = 0 ; i < (int)_cases.size() ; i++ )
	{		
		/* On ne teste pas la case appelante avec elle même */
		if ( _cases[i] != this )
		{
			bool estVoisine = false;
						
			for ( int j = 0 ; j < (int)_cases[i]->getNbPts() && estVoisine == false ; j++ )
			{
				for ( int k = 0 ; k < (int)pol.getNbPts() && estVoisine == false ; k++ )
				{
					if ( _cases[i]->getPoint(j) == pol.getPoint(k) )
					{
						Case* tmp = _cases[i];
						estVoisine = true;
						voisins.push_back ( tmp );
					}
				}
			}
		}
	}
	
	bord = this->isBord( _cases );
}

bool Case::isBord(vector<Case *> _cases)
{
	for ( int i = 0 ; i < pol.getNbPts() ; i++ )
	{
		bool ptDeBord = true;
		
		for ( int j = 0 ; j < (int) _cases.size() ; j++ )
		{		
			if ( _cases[j] != this )
			{
				for ( int k = 0 ; k < (int)_cases[j]->getNbPts() ; k++ )
				{
					if ( _cases[j]->getPoint(k) == pol.getPoint(i) )
						ptDeBord = false;
				}
			}
		}
		
		if ( ptDeBord )
		{
			return true;
		}
	}
	
	return false;
}

int Case::getNbVoisins()
{
	return (int)voisins.size();
}

bool Case::isEmpty()
{
	return pol.isEmpty();
}

void Case::clear()
{
	this->voisins.clear();
	bord = false;
	type = PLAINE;
	this->pol.clear();
	nbPions = 0;
	ent = NULL;
	jou = NULL;
}

bool Case::contains(Point *_p)
{
	return pol.contains(_p);
}

bool Case::contains( int _x, int _y )
{
	return pol.contains(_x, _y);
}

void Case::print()
{
	pol.print();
}

void Case::display()
{
	pol.display();
}

void Case::display(float _r, float _g, float _b)
{
	pol.display( _r, _g, _b);
}

void Case::displayFilled(float _r, float _g, float _b)
{
	pol.displayFilled(_r,_g,_b);
}

void Case::displayFilled(float _r, float _g, float _b, float _a)
{
	pol.displayFilled(_r,_g,_b,_a);
}

void Case::displayNeighbourhood(float _r, float _g, float _b)
{
	for ( int i = 0 ; i < (int)voisins.size() ; i++ )
	{
		voisins[i]->displayFilled(_r,_g,_b,0.5);
	}
}

void Case::displayType()
{
	pol.displayText( type );
}

void Case::displayNbPions()
{
	char tmp[10];
	sprintf( tmp, "\n%d Pions", nbPions );
	pol.displayText( QString (tmp) );
}

void Case::displayPions(Image _i)
{
	pol.displayPions( nbPions, _i );
}
